package top.laoshuzi.common.mvp.presenter;

import android.support.annotation.Nullable;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import io.reactivex.Observable;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.BiConsumer;
import io.reactivex.functions.Consumer;
import io.reactivex.subjects.BehaviorSubject;
import top.laoshuzi.common.mvp.presenter.delivery.DeliverFirst;
import top.laoshuzi.common.mvp.presenter.delivery.DeliverLatestCache;
import top.laoshuzi.common.mvp.presenter.delivery.DeliverReplay;
import top.laoshuzi.common.mvp.presenter.delivery.Delivery;
import top.laoshuzi.common.mvp.view.OptionalView;

public class RxPresenter<View> extends Presenter<View> {

    private final CompositeDisposable disposables = new CompositeDisposable();
//    private final BehaviorSubject<OptionalView<View>> views = BehaviorSubject.create();

    private final HashMap<Integer, Factory<Disposable>> restartables = new HashMap<>();
    private final HashMap<Integer, Disposable> restartableDisposables = new HashMap<>();
    private final ArrayList<Integer> requested = new ArrayList<>();

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
//        views.onComplete();
        disposables.dispose();
        for (Map.Entry<Integer, Disposable> entry : restartableDisposables.entrySet())
            entry.getValue().dispose();
    }

    public void add(Disposable disposable) {
        this.disposables.add(disposable);
    }

    public void remove(Disposable disposable) {
        this.disposables.remove(disposable);
    }


    public void restartable(int restartableId, Factory<Disposable> factory) {
        restartables.put(restartableId, factory);
        if (requested.contains(restartableId))
            start(restartableId);
    }

    public void start(int restartableId) {
        stop(restartableId);
        requested.add(restartableId);
        restartableDisposables.put(restartableId, restartables.get(restartableId).create());
    }

    public void stop(int restartableId) {
        requested.remove((Integer) restartableId);
        Disposable disposable = restartableDisposables.get(restartableId);
        if (disposable != null)
            disposable.dispose();
    }

    public boolean isDisposed(int restartableId) {
        Disposable disposable = restartableDisposables.get(restartableId);
        return disposable == null || disposable.isDisposed();
    }

//    public <T> void restartableFirst(int restartableId, final Factory<Observable<T>> observableFactory,
//                                     final BiConsumer<View, T> onNext, @Nullable final BiConsumer<View, Throwable> onError) {
//        restartable(restartableId, new Factory<Disposable>() {
//            @Override
//            public Disposable create() {
//                return observableFactory.create()
//                        .compose(RxPresenter.this.<T>deliverFirst())
//                        .subscribe(split(onNext, onError));
//            }
//        });
//    }
//
//    public <T> void restartableFirst(int restartableId, final Factory<Observable<T>> observableFactory, final BiConsumer<View, T> onNext) {
//        restartableFirst(restartableId, observableFactory, onNext, null);
//    }
//
//    public <T> void restartableLatestCache(int restartableId, final Factory<Observable<T>> observableFactory, final BiConsumer<View, T> onNext, @Nullable final BiConsumer<View, Throwable> onError) {
//
//        restartable(restartableId, new Factory<Disposable>() {
//            @Override
//            public Disposable create() {
//                return observableFactory.create()
//                        .compose(RxPresenter.this.<T>deliverLatestCache())
//                        .subscribe(split(onNext, onError));
//            }
//        });
//    }
//
//    public <T> void restartableLatestCache(int restartableId, final Factory<Observable<T>> observableFactory, final BiConsumer<View, T> onNext) {
//        restartableLatestCache(restartableId, observableFactory, onNext, null);
//    }
//
//    public <T> void restartableReplay(int restartableId, final Factory<Observable<T>> observableFactory,
//                                      final BiConsumer<View, T> onNext, @Nullable final BiConsumer<View, Throwable> onError) {
//
//        restartable(restartableId, new Factory<Disposable>() {
//            @Override
//            public Disposable create() {
//                return observableFactory.create()
//                        .compose(RxPresenter.this.<T>deliverReplay())
//                        .subscribe(split(onNext, onError));
//            }
//        });
//    }


//    public Observable<OptionalView<View>> view() {
//        return views;
//    }
//
//    public <T> DeliverLatestCache<View, T> deliverLatestCache() {
//        return new DeliverLatestCache<>(views);
//    }
//
//    public <T> DeliverFirst<View, T> deliverFirst() {
//        return new DeliverFirst<>(views);
//    }
//
//    public <T> DeliverReplay<View, T> deliverReplay() {
//        return new DeliverReplay<>(views);
//    }

//    public <T> void restartableReplay(int restartableId, final Factory<Observable<T>> observableFactory, final BiConsumer<View, T> onNext) {
//        restartableReplay(restartableId, observableFactory, onNext, null);
//    }
//
//    public <T> Consumer<Delivery<View, T>> split(final BiConsumer<View, T> onNext, @Nullable final BiConsumer<View, Throwable> onError) {
//        return new Consumer<Delivery<View, T>>() {
//            @Override
//            public void accept(Delivery<View, T> delivery) throws Exception {
//                delivery.split(onNext, onError);
//            }
//        };
//    }
//
//    public <T> Consumer<Delivery<View, T>> split(BiConsumer<View, T> onNext) {
//        return split(onNext, null);
//    }

}
